﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
using System.Threading;

namespace CXW.Core
{
    /// <summary>这个类包含了两个资源，处理应用程序的字符串和非字符串资源。</summary>
    public static class ResourceService
    {
        const string uiLanguageProperty = "Properties.UILanguage";
         
        public static string ResourceDirectory { get; private set; }

        public static void InitializeService(string resourceDirectory)
        {
            if (ResourceDirectory != null)
                throw new InvalidOperationException("Service is already initialized.");
            if (resourceDirectory == null)
                throw new ArgumentNullException("resourceDirectory");

            ResourceDirectory = resourceDirectory;

            PropertyService.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChange);
            LoadLanguageResources(ResourceService.Language);
        }

        public static string Language
        {
            get
            {
                return PropertyService.Get(uiLanguageProperty, Thread.CurrentThread.CurrentUICulture.Name);
            }
            set
            {
                if (Language != value)
                {
                    PropertyService.Set(uiLanguageProperty, value);
                }
            }
        }

        static readonly object loadLock = new object();

        /// <summary>English strings (list of resource managers)</summary>
        static List<ResourceManager> strings = new List<ResourceManager>();
        /// <summary>Neutral/English images (list of resource managers)</summary>
        static List<ResourceManager> icons = new List<ResourceManager>();

        /// <summary>
        /// Registers string resources in the resource service.
        /// </summary>
        /// <param name="baseResourceName">The base name of the resource file embedded in the assembly.</param>
        /// <param name="assembly">The assembly which contains the resource file.</param>
        /// <example><c>ResourceService.RegisterStrings("TestAddin.Resources.StringResources", GetType().Assembly);</c></example>
        public static void RegisterStrings(string baseResourceName, Assembly assembly)
        {
            RegisterNeutralStrings(new ResourceManager(baseResourceName, assembly) { IgnoreCase = true });
        }

        public static void RegisterNeutralStrings(ResourceManager stringManager)
        {
            strings.Add(stringManager);
        }

        /// <summary>
        /// Registers image resources in the resource service.
        /// </summary>
        /// <param name="baseResourceName">The base name of the resource file embedded in the assembly.</param>
        /// <param name="assembly">The assembly which contains the resource file.</param>
        /// <example><c>ResourceService.RegisterImages("TestAddin.Resources.BitmapResources", GetType().Assembly);</c></example>
        public static void RegisterImages(string baseResourceName, Assembly assembly)
        {
            RegisterNeutralImages(new ResourceManager(baseResourceName, assembly) { IgnoreCase = true });
        }

        public static void RegisterNeutralImages(ResourceManager imageManager)
        {
            icons.Add(imageManager);
        }

        static void OnPropertyChange(object sender, PropertyChangedEventArgs e)
        {
            if (e.Key == uiLanguageProperty && e.NewValue != e.OldValue)
            {
                LoadLanguageResources((string)e.NewValue);

                if (LanguageChanged != null)
                    LanguageChanged(null, e);
            }
        }

        public static event EventHandler ClearCaches;

        public static event EventHandler LanguageChanged;
        static string currentLanguage;

        static void LoadLanguageResources(string language)
        {
            lock (loadLock)
            {
                try
                {
                    Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
                }
                catch (Exception)
                {
                    try
                    {
                        Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language.Split('-')[0]);
                    }
                    catch (Exception) { }
                }

                currentLanguage = language;
            }

            if (ClearCaches != null)
                ClearCaches(null, EventArgs.Empty);
        }


        /// <summary>从资源数据库返回一个字符串，它为用户处理透明的本地化。</summary>
        /// <param name="name">请求资源的名称。</param>
        /// <returns>（本地化）资源数据库中的字符串(找不到请求的资源时返回传入参数)。</returns>
        public static string GetString(string name)
        {
            lock (loadLock)
            {
                if (string.IsNullOrWhiteSpace(name)) { return null; }

                string s = null;

                foreach (ResourceManager resourceManger in strings)
                {
                    try { s = resourceManger.GetString(name); }
                    catch (Exception) { }

                    if (s != null) { break; }
                }

                if (s == null)
                {
                    //throw new CoreException("Resource not found : " +"string >" + name + "<");
                    s = name;
                }

                return s;
            }
        }

        public static object GetObject(string name)
        {
            lock (loadLock)
            {
                object iconobj = null;
                if (!string.IsNullOrWhiteSpace(name))
                {
                    foreach (ResourceManager resourceManger in icons)
                    {
                        try { iconobj = resourceManger.GetObject(name); }
                        catch (Exception) { }

                        if (iconobj != null) { break; }
                    }
                }
                return iconobj;
            }
        }
    }
}
